package com.lintesis.lintesisview.common;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.CreateEvent;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.ForwardEvent;
import org.zkoss.zul.Borderlayout;
import org.zkoss.zul.Button;
import org.zkoss.zul.Checkbox;
import org.zkoss.zul.FieldComparator;
import org.zkoss.zul.Listbox;
import org.zkoss.zul.Listheader;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Paging;
import org.zkoss.zul.Textbox;
import org.zkoss.zul.Window;


import com.lintesis.lintesismodel.common.hibernate.BussinessObject;
import com.lintesis.lintesismodel.common.hibernate.GenericDAO;
import com.lintesis.lintesismodel.common.hibernate.HibernateSearchObject;
import com.lintesis.lintesisview.common.menu.UserWorkspace;
import com.lintesis.lintesisview.common.util.MultiLineMessageBox;
import com.lintesis.lintesisview.common.util.pagging.PagedListWrapper;
import com.trg.search.Filter;
import com.trg.search.SearchResult;

public abstract class ListCtrl<T extends BussinessObject> extends BaseCtrl
{
	/**
	 * 
	 */
	public abstract String getEntityName();
 
	protected PagedListWrapper<T> listModelEntity;
	protected GenericDAO<T> genericDAO = new GenericDAO<T>(UserWorkspace.getInstance().gethSession());
	protected HibernateSearchObject<T> hibernateSearchObject = null;

	protected Window window;
	protected Borderlayout borderLayoutList;
	private static final long serialVersionUID = -2343963528927654L;

	protected HashMap<String, Listheader> orders = new HashMap<String, Listheader>();
	protected HashMap<String, Boolean> defaultOrders = new HashMap<String, Boolean>();
	protected Vector<Object> searchComponents = new Vector<Object>();
	protected HashMap<String, Object> filters = new HashMap<String, Object>();
	protected int countRows;
	protected transient Paging pagingList; // autowired
	protected Listbox listBoxEntity;
	protected Checkbox checkShowAll;
	protected Button btNew;
	protected Button btSearch;
	protected transient Textbox lbLargeDescription;
	public Object objeto;

	public Object getObjeto()
	{
		return objeto;
	}

	public void setObjeto(Object objeto)
	{
		this.objeto = objeto;
	}

	protected HibernateSearchObject<T> getNewHibernateSearchObject()
	{
		return new HibernateSearchObject<T>(getNewEntidad().getClass());
	}

	protected GenericDAO<T> getGenericDao()
	{
		return genericDAO;
	}

	protected abstract void doDefineOrders();

	public PagedListWrapper<T> getListModelEntity()
	{
		return listModelEntity;
	}

	public void setListModelEntity(PagedListWrapper<T> listModelEntity)
	{
		this.listModelEntity = listModelEntity;
	}

	public void setListboxToolTiptext()
	{
		String label = Labels.getLabel("listbox.tooltiptext");
		String label2 = Labels.getLabel(getEntityName());
		if (label2 == null)
		{
			System.out.println(getEntityName() + " Not Found");
			label2 = "";
		}
		listBoxEntity.setTooltiptext(label + " " + label2);
	}

	public void setBtnNewTooltiptext()
	{
		if (btNew == null)
			return;
		String label = Labels.getLabel("listbox.new");
		String label2 = Labels.getLabel(getEntityName());
		if (label2 == null)
		{
			System.out.println(getEntityName() + " Not Found");
			label2 = "";
		}

		btNew.setTooltiptext(label + " " + label2);
	}

	public void setBtnSearchTooltiptext()
	{
		if (btSearch == null)
			return;
		String label = Labels.getLabel("listbox.search");
		String label2 = Labels.getLabel(getEntityName());
		if (label2 == null)
		{
			System.out.println(getEntityName() + " Not Found");
			label2 = "";
		}

		btSearch.setTooltiptext(label + " " + label2);
	}

	public void onCreate$window(Event event) throws Exception
	{
		hibernateSearchObject = getNewHibernateSearchObject();

		doCreateWindow(event);

	}

	public abstract void doSetSearchComponents();

	public void doSetOrders()
	{
		doDefineOrders();
		for (String keys : orders.keySet())
		{
			Listheader lh = orders.get(keys);

			lh.setSortDescending(new FieldComparator(keys, false));
			lh.setSortAscending(new FieldComparator(keys, true));
		}
	}

	public HibernateSearchObject<T> getHibernateSearchObject()
	{
		if (hibernateSearchObject == null)
			hibernateSearchObject = getNewHibernateSearchObject();
		return hibernateSearchObject;
	}

	public void doOnCreateCommon(Window w, Event fe) throws Exception
	{
		doOnCreateCommon(w);
		CreateEvent ce = (CreateEvent) ((ForwardEvent) fe).getOrigin();
		args = (Map<String, Object>) ce.getArg();
		doSetOrders();
		doCheckRights();

	}

	protected abstract void setSearchFilters();

	public void onCheck$checkShowAll(Event event)
	{
		doClearSearchValues();
		checkShowAll.setChecked(true);
		setSearchFilters();
		doSearch();
	}

	protected void doClearSearchValues()
	{
		doSetSearchComponents();
		for (Object c : searchComponents)
		{
			try
			{
				c.getClass().getMethod("setText", String.class).invoke(c, (String) null);
			} catch (IllegalArgumentException e)
			{
				e.printStackTrace();
			} catch (SecurityException e)
			{
				e.printStackTrace();
			} catch (IllegalAccessException e)
			{
				e.printStackTrace();
			} catch (InvocationTargetException e)
			{
				e.printStackTrace();
			} catch (NoSuchMethodException e)
			{
				e.printStackTrace();
			}
		}
		filters.clear();
		setDefaultFilters();
	}

	public void onClick$btSearch(Event event)
	{
		checkShowAll.setChecked(false);
		setSearchFilters();
		doSearch();
	}

	public void onClick$btNew(Event event) throws Exception
	{

		BussinessObject entidad = getNewEntidad();

		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("entidad", entidad);
		map.put("lbEntidad", listBoxEntity);
		map.put("entidadCtrl", this);

		Window win = null;
		try
		{
			win = (Window) Executions.createComponents(getABMDialogURL(), null, map);
		} catch (Exception e)
		{
			e.printStackTrace();

			// Show a error box
			String msg = e.getMessage();
			String title = Labels.getLabel("message_Error");

			MultiLineMessageBox.doSetTemplate();
			MultiLineMessageBox.show(msg, title, MultiLineMessageBox.OK, "ERROR", true);

			if (win != null)
			{
				win.detach();
			}
		}

	}

	public void doSearch()
	{
		getHibernateSearchObject().clearFilters();
		UserWorkspace.getInstance().gethSession().clear();
		setDefaultFilters();
		for (String key : filters.keySet())
		{
			if (filters.get(key) != null && !filters.get(key).equals("%%"))

				if (filters.get(key) instanceof String)
					getHibernateSearchObject().addFilterILike(key, filters.get(key).toString());
				else if (!(filters.get(key) instanceof Filter))
					getHibernateSearchObject().addFilterEqual(key, filters.get(key));
				else
					getHibernateSearchObject().addFilter((Filter) filters.get(key));

		}
		for (String key : defaultOrders.keySet())
		{
			getHibernateSearchObject().addSort(key, defaultOrders.get(key));
		}
		SearchResult<T> initialList = getGenericDao().getSRBySearchObject(getHibernateSearchObject(), 0, countRows);

	//	pagingList.setPageSize(countRows);
		pagingList.setDetailed(true);

		setListModelEntity(new PagedListWrapper<T>(listBoxEntity, pagingList, initialList, getHibernateSearchObject()));

		if (this.getObjeto() != null)
		{
			//getHibernateSearchObject().clearFilters();
			//initialList = getGenericDao().getSRBySearchObject(getHibernateSearchObject(), 0, countRows);
			//pagingList.setPageSize(countRows);
			//pagingList.setDetailed(true);

			//setListModelEntity(new PagedListWrapper<T>(listBoxEntity, pagingList, initialList, getHibernateSearchObject()));
			//Se comentan las 5 líneas anteriores porque estaban borrando los filtros (permisos) del usuario y esto hacia que
			//la aplicación mostrara todos los objetos en vez de mostrar solo aquellos que tiene permitido ver.
			
			this.setActivePages(this.getObjeto());
			

			int id = this.searchObject(initialList.getResult(), this.getObjeto());
			this.listBoxEntity.setSelectedIndex(id);
			this.setObjeto(null);		
		} else
		{
			binder.loadAll();			
		}
	}

	// método que inicializa la lista en la página donde se encuentra el
	// registro modificado o agregado
	public void setActivePages(Object object1)
	{
		//this.hibernateSearchObject = null;
		setDefaultFilters();//Se agrega esta línea para setear los filtros (permisos)
		SearchResult<T> initialList1 = getGenericDao().getSRBySearchObject(getHibernateSearchObject(), 0, 0);
		List<T> list = initialList1.getResult();
	
		int id = this.searchObject(list, object1);
		int position = id / countRows;

		listModelEntity.refreshModel(getHibernateSearchObject(), position * countRows, countRows);

		pagingList.setActivePage(position);
	}
	
	public int searchObject(List<T> list, Object o){
		int id = 0;
		int i = 0;
		for(Object ob: list){
			if(((BussinessObject) ob).getId().equals(((BussinessObject) o).getId())){
				id = i;
				break;
			}	
			i++;
		}
		return id;
	}

	protected abstract void setDefaultFilters();

	protected void doCreateWindow(Event event) throws Exception
	{
		setListboxToolTiptext();
		setBtnNewTooltiptext();
		setBtnSearchTooltiptext();
		int maxListBoxHeight = (UserWorkspace.getInstance().getCurrentDesktopHeight() - 152);
		
		countRows = pagingList.getPageSize();
		
//		countRows = 24;
//		countRows = Math.round(maxListBoxHeight / 22);

//		listBoxEntity.setPageSize(countRows);


		borderLayoutList.setHeight(String.valueOf(maxListBoxHeight) + "px");
		doOnCreateCommon(window, event);
		if (checkShowAll != null)
			checkShowAll.setChecked(true);
		doClearSearchValues();
		setSearchFilters();
		doSearch();

	}

	public Borderlayout getBorderLayoutList()
	{
		return borderLayoutList;
	}

	public void setBorderLayoutList(Borderlayout borderLayoutList)
	{
		this.borderLayoutList = borderLayoutList;
	}

	public Paging getPagingList()
	{
		return pagingList;
	}

	public void setPagingList(Paging pagingList)
	{
		this.pagingList = pagingList;
	}

	public void onClicked(Event event)
	{
		setDescripcionLarga();
	}

	protected abstract void setDescripcionLarga();

	public T getSelectedEntidad()
	{
		Listitem selected = listBoxEntity.getSelectedItem();
		if (selected != null && selected.getValue() != null)
		{
			return (T) selected.getValue();
		}
		return null;
	}

	public void onDoubleClicked(Event event) throws Exception
	{

		// get the selected object
		Listitem item = listBoxEntity.getSelectedItem();
		// this.setActivePages();
		if (item != null)
		{
			// store the selected customer object
			BussinessObject bo = (BussinessObject) item.getValue();
			bo.putSession(UserWorkspace.getInstance().gethSession());

			// ConnectionManager.getSession().connection();
			// if(estado == false){
			// h
			// }

			HashMap<String, Object> map = new HashMap<String, Object>();
			map.put("entity", bo);
			map.put("lbEntidad", listBoxEntity);
			map.put("entidadCtrl", this);

			Window win = null;
			try
			{
				win = (Window) Executions.createComponents(getABMDialogURL(), null, map);
			} catch (Exception e)
			{
				// Show a error box
				String msg = e.getMessage();
				String title = Labels.getLabel("message_Error");

				MultiLineMessageBox.doSetTemplate();
				MultiLineMessageBox.show(msg, title, MultiLineMessageBox.OK, "ERROR", true);

				if (win != null)
				{
					win.detach();
				}
			}

		}
	}

	protected abstract String getABMDialogURL();

	protected abstract BussinessObject getNewEntidad();

	public void onClick$btOpen(Event event) throws Exception
	{
		listBoxEntity.setSelectedItem((Listitem) ((ForwardEvent) event).getOrigin().getTarget().getParent().getParent());
		onDoubleClicked(event);
	}
}
